﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Collections;

namespace MRS.WebUI
{
    public class ActiveUserHandler
    {
        static log4net.ILog _logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        private static MRS.DBL.BLL.UserMgr _UserMgrBLL = null;

        /// <summary>
        /// 单列对象
        /// </summary>
        private static ActiveUserHandler _Instance = null;
        /// <summary>
        /// 活跃用户列表
        /// </summary>
        private static Dictionary<int, MRS.DBL.Model.User> _ActiveUserList = null;

        public static object obj = new object();
        public static bool flag = true;
        private const int HeartbeatInterval = 30;   //心跳 30 秒
        static System.Threading.Thread _ActiveUserThread = null;
        private static bool _needClearOnlineFlag = true;// 是否需要清除在线列表的标志

        private ActiveUserHandler() 
        {
            _ActiveUserThread = new System.Threading.Thread(CheckUserIsActive);
            _ActiveUserThread.IsBackground = true;

            _ActiveUserThread.Start();
        }
        /// <summary>
        /// 单列
        /// </summary>
        /// <returns></returns>
        public static ActiveUserHandler Instance() 
        {
            if (_Instance == null)
            {
                _Instance = new ActiveUserHandler();

                if (_ActiveUserList == null)
                    _ActiveUserList = new Dictionary<int, DBL.Model.User>();

                if (_UserMgrBLL == null)
                    _UserMgrBLL = new DBL.BLL.UserMgr();
            }
            return _Instance;
        }

        /// <summary>
        /// 加入活跃用户列表
        /// </summary>
        /// <param name="oUser"></param>
        public void JoinActiveUserList(MRS.DBL.Model.User oUser) 
        {
            if (oUser == null)
                return;
            lock (obj)
            {
                if (_ActiveUserList.ContainsKey(oUser.Id))//已存在，更新值
                {
                    oUser.LastActiveTime = DateTime.Now;//设置最后活动时间
                    _ActiveUserList[oUser.Id] = oUser;
                    return;
                }
                _ActiveUserList.Add(oUser.Id, oUser);//添加到活跃用户列表中
                _logger.InfoFormat("User:{0} Join ActiveUserList", oUser.Id);
            }
        }

        /// <summary>
        /// 将指定用户移除活跃列表并更新数据库用户在线状态
        /// </summary>
        /// <param name="key"></param>
        public void RemoveUser(int key) 
        {
            if (_ActiveUserList.ContainsKey(key))
            {
                _ActiveUserList.Remove(key);//移除活跃用户
                ChangeUserStatus(key, false);
                _logger.InfoFormat("User:{0} Removed From ActiveUserList", key);
            }
        }

        /// <summary>
        /// 修改用户在线状态
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="isOnlie"></param>
        private void ChangeUserStatus(int userId,bool isOnlie) 
        {
            _UserMgrBLL.ChangeUserOnLineStatus(userId, isOnlie);
        }


        /// <summary>
        /// 修改所有活跃用户列表中的用户在线状态
        /// </summary>
        /// <param name="isOnlie"></param>
        private void SetAllActiveUserOnlineStatus(bool isOnlie) 
        {
            foreach (int key in _ActiveUserList.Keys) 
            {
                ChangeUserStatus(key, isOnlie);
            }
        }


        /// <summary>
        /// 功能：检查personList活动用户列表。如果有用户超时，从列表中删除，再删除对应的心跳线程
        /// 频率：1次/min
        /// </summary>
        private void CheckUserIsActive()
        {
            ArrayList lstOffline = new ArrayList(); //下线用户列表
            while (flag)
            {
                System.Threading.Thread.Sleep(10000);//线程挂起 1 分钟

                if (_ActiveUserList.Count < 1)
                    continue;

                lock (obj)
                {
                    foreach (int key in _ActiveUserList.Keys)
                    {
                        MRS.DBL.Model.User oUser = null;
                        bool result = _ActiveUserList.TryGetValue(key, out oUser);
                        if (result)
                        {
                            long nInterval = (System.DateTime.Now.Ticks - oUser.LastActiveTime.Ticks) / 10000000; //Ticks 中 10000000 表示 一秒
                            if (nInterval >= HeartbeatInterval * 2)//用户最后活跃时间与当前系统时间间隔超过指定时间，踢出活跃用户列表
                            {
                                lstOffline.Add(oUser.Id);
                            }
                        }
                    }
                }

                // 移除掉离线用户
                foreach (int userid in lstOffline)
                {
                    RemoveUser(userid); //注销用户
                }
                lstOffline.Clear();
            }
        }

        /// <summary>
        /// 心跳，表示用户在线
        /// </summary>
        /// <param name="userid"></param>
        public void Heartbeat(int userid)
        {
            MRS.DBL.Model.User oActiveUser = null;
            
            if (_ActiveUserList.ContainsKey(userid)) //存在对象，直接更新状态
            {
                bool getValueResult = _ActiveUserList.TryGetValue(userid, out oActiveUser);
                if (oActiveUser != null)
                {
                    oActiveUser.LastActiveTime = System.DateTime.Now;   //活动时间
                    _ActiveUserList[userid] = oActiveUser;
                }
                _logger.InfoFormat("heartbeat from {0} (int ActiveUserList)", userid);
            }
            else //不存在对象，创建
            {
                oActiveUser = _UserMgrBLL.GetModel(userid);//获取用户对象
                lock (obj)
                {
                    oActiveUser.LastActiveTime = DateTime.Now;//最后活动时间
                    _ActiveUserList.Add(userid, oActiveUser);//加入在线列表
                }
                _logger.InfoFormat("heartbeat from {0} (add to ActiveUserList)", userid);
            }
        }

        /// <summary>
        /// 获取活跃用户
        /// </summary>
        /// <returns></returns>
        public MRS.DBL.Model.User[] GetActiveUserList() 
        {
            if (_ActiveUserList == null || _ActiveUserList.Count < 1)
                return null;
            
            List<MRS.DBL.Model.User> activeList = new List<DBL.Model.User>();
            
            MRS.DBL.Model.User oUser = null;
            foreach (int key in _ActiveUserList.Keys)
            {
                _ActiveUserList.TryGetValue(key,out oUser);//从活跃用户列表中取出活跃用户
                if (oUser == null)
                    continue;
                activeList.Add(oUser);
            }
            return activeList.ToArray();
        }
    }
}